﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FCDB.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.Core;
using System.Data.Entity.Validation;


namespace FCDB.Repository
{
   public abstract class LogicBase
    {
       NLog.Logger _logger = NLog.LogManager.GetCurrentClassLogger();

       public static FCDBEntities DBHelper
        {
            get
            {
                
                return ObjectContextHelper.CurrentObjectContext;
            }
        }

       //private static IList<String> m_FCDBCompanyList;
       //public  static IList<String> FCDBCompanyList
       //{

       //    get
       //    {
       //        if(m_FCDBCompanyList==null)
       //        {
       //            m_FCDBCompanyList = new List<String>();
       //            m_FCDBCompanyList.Add("C1");
       //            m_FCDBCompanyList.Add("C3");
       //        }
       //        return m_FCDBCompanyList;
       //    }
       //  }
       // private static IList<String> m_FCDBDepartmentList;
       //public  static IList<String> FCDBDepartmentList
       //{

       //    get
       //    {
       //        if(m_FCDBDepartmentList==null)
       //        {
       //            m_FCDBDepartmentList = new List<String>();
       //            m_FCDBDepartmentList.Add("D1");
       //            m_FCDBDepartmentList.Add("D1005");
       //            m_FCDBDepartmentList.Add("D2");
       //            m_FCDBDepartmentList.Add("D3");
       //            m_FCDBDepartmentList.Add("D30");
       //            m_FCDBDepartmentList.Add("D335");
       //            m_FCDBDepartmentList.Add("D19");
       //            m_FCDBDepartmentList.Add("D20");
       //            m_FCDBDepartmentList.Add("D1005"); 
       //             m_FCDBDepartmentList.Add("D202"); 
       //              m_FCDBDepartmentList.Add("D21");
       //              m_FCDBDepartmentList.Add("D22");
       //              m_FCDBDepartmentList.Add("D23");
       //              m_FCDBDepartmentList.Add("D26");
       //              m_FCDBDepartmentList.Add("D27");
       //              m_FCDBDepartmentList.Add("D40");
       //              m_FCDBDepartmentList.Add("D46");
       //              m_FCDBDepartmentList.Add("D510");
       //              m_FCDBDepartmentList.Add("D4001");
       //              m_FCDBDepartmentList.Add("D4002");
                   
       //        }
       //        return m_FCDBDepartmentList;
       //    }
       //  }  
       












        public virtual T Get<T>(long id)
        {

            Type t = typeof(T);
            var context = ((IObjectContextAdapter)DBHelper).ObjectContext;
            EntityKey key = new  EntityKey(string.Format("{0}.{1}", context.DefaultContainerName, t.Name), "ID", id);
            Object originalItem;
            try
            {
                //using (myfoodflatEntities context = DBHelper)
                //{ 
                if (context.TryGetObjectByKey(key, out originalItem))
                {
                    return (T)originalItem;
                }
                return default(T);
                //}
            }
            catch (Exception ex)
            {
                throw ex;
            } 
        }

        public virtual T GetByKey<T>(Object id)
        {
            T entity=(T)DBHelper.Set(typeof(T)).Find(id);
            return entity;
        }

        public virtual void UpdateByNoSave(object entity)
        {
            Type t = entity.GetType();
            EntityKey key;
            object originalItem;
            
            var context = ((IObjectContextAdapter)DBHelper).ObjectContext;
            key = context.CreateEntityKey(t.Name, entity);
            if (context.TryGetObjectByKey(key, out originalItem))
            {
                context.ApplyCurrentValues(key.EntitySetName, entity);
            }
           
        }
        public int SaveChagnes()
        {
            try
            {
                return DBHelper.SaveChanges();
            }
            catch (DbEntityValidationException e)
            {
                DbEntityValidationHandler(e);
                return -1;
            }
            catch (Exception ex)
            {
                _logger.ErrorException(ex.Message, ex);

                return -1;
            }
           
        }
        public virtual int Update(object entity)
        {
            try
            {
                UpdateByNoSave(entity); 
               return   DBHelper.SaveChanges(); 
            }
            catch (DbEntityValidationException e)
            {
                DbEntityValidationHandler(e);
                return -1;
            }
            catch (Exception ex)
            {
                _logger.ErrorException(ex.Message, ex);
                return -1;
            }
            
        }
        protected virtual void AddByNoSave(Object entity)
        {
            Type t = entity.GetType();
            var context = ((IObjectContextAdapter)DBHelper).ObjectContext;
            context.AddObject(t.Name, entity);
        }

        public virtual int Add(Object entity)
        {
            try
            {
                //using (myfoodflatEntities context = DBHelper)
                //{
                AddByNoSave(entity);
                return DBHelper.SaveChanges();
                //}
            }
            catch (DbEntityValidationException e)
            {
                DbEntityValidationHandler(e);
                return -1;
            }
            catch (Exception ex)
            {
                _logger.ErrorException(ex.Message, ex);
                return -1;
            }

        }

        public virtual int Delete<T>(long id)
        {
            T entity = Get<T>(id);
            return Delete(entity);

        }
        protected virtual void DeleteByNoSave<T>(long id)
        {
            T entity = Get<T>(id);
            DeleteByNoSave(id);
        }
        protected virtual void DeleteByNoSave(Object entity)
        {
            var context = ((IObjectContextAdapter)DBHelper).ObjectContext;
            context.DeleteObject(entity);
        }
        public virtual int Delete(Object entity)
        {
            try
            {
                //using (myfoodflatEntities context = DBHelper)
                //{
                DeleteByNoSave(entity);
                return DBHelper.SaveChanges();
                //}
            }
            catch (Exception ex)
            {
                _logger.ErrorException(ex.Message, ex);
                return -1;
            }

        }

       /// <summary>
        /// 获取相应分页实体
       /// </summary>
       /// <typeparam name="T"></typeparam>
       /// <param name="skip"></param>
       /// <param name="take">一页多少条记录</param>
       /// <param name="total">总数</param>
        /// <param name="strWhere">针对表中属性行添加it,例如：it.ID</param>
        /// <param name="orderbyList">针对表中属性行添加it,例如：it.ID=1232</param>
       /// <returns></returns>
        public virtual IList<T> GetPageList<T>(int skip, int take, out int total,string strWhere=null,IList<string> orderbyList=null)
        {
            try
            {
                var context = ((IObjectContextAdapter)DBHelper).ObjectContext;
                Type t = typeof(T);
                String strquery = string.Format("SELECT VALUE CENTITY from {0}.{1} AS CENTITY", context.DefaultContainerName, t.Name);
                System.Data.Entity.Core.Objects.ObjectQuery<T> query = context.CreateQuery<T>(strquery);
                if (!string.IsNullOrEmpty(strWhere))
                {
                    query = query.Where(strWhere);
                }
                total = query.Count();

                if (orderbyList == null || orderbyList.Count == 0)
                {
                    var hquery = query.OrderBy("it.ID DESC").Skip(skip).Take(take);
                    return hquery.ToList();
                }
                else
                {
                    foreach (string str in orderbyList)
                    {
                        query = query.OrderBy(str);
                    }
                    var hquery = query.Skip(skip).Take(take);
                    return hquery.ToList();
                }
            }
            catch (Exception ex)
            {
                _logger.Error(ex.Message);
                throw(ex);
            }
        }
       /// <summary>
       ///  获取相应实体
       /// </summary>
       /// <typeparam name="T"></typeparam>
       /// <param name="strWhere">针对表中属性行添加it,例如：it.ID</param>
        /// <param name="orderbyList">针对表中属性行添加it,例如：it.ID=1232</param>
       /// <returns></returns>
        public virtual IList<T> GetAll<T>(string strWhere = null, IList<string> orderbyList = null)
        {
            try
            { 
            var context = ((IObjectContextAdapter)DBHelper).ObjectContext;
            Type t = typeof(T);
            String strquery = string.Format("SELECT VALUE CENTITY from {0}.{1} AS CENTITY",context.DefaultContainerName, t.Name);
            System.Data.Entity.Core.Objects.ObjectQuery<T> query = context.CreateQuery<T>(strquery);
            if (!string.IsNullOrEmpty(strWhere))
            {
               query= query.Where(strWhere);
            }
            if (orderbyList == null || orderbyList.Count == 0)
            {
                return query.OrderBy("it.ID DESC").ToList();
                
            }
            else
            {
                foreach (string str in orderbyList)
                {
                    query = query.OrderBy(str);
                }
                return    query.ToList(); 
            }
            }
            catch (Exception ex)
            {

                _logger.Error(ex.Message);
                throw (ex);
            }
            
        }
        #region Exception handler

        void DbEntityValidationHandler(DbEntityValidationException ex)
        {
            foreach (var eve in ex.EntityValidationErrors)
            {
                _logger.Error("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
                    eve.Entry.Entity.GetType().Name, eve.Entry.State);

                foreach (var ve in eve.ValidationErrors)
                {
                    _logger.Error("- Property: \"{0}\", Error: \"{1}\"",
                    ve.PropertyName, ve.ErrorMessage);
                }
            }
        }

        #endregion

    }
}
